from string import ascii_letters, digits
import time, datetime, os, hashlib
import random
import logging
from google.appengine.api import users
from google.appengine.ext import webapp, db
from google.appengine.api import users
from google.appengine.ext.webapp import template
from google.appengine.api import xmpp

from logger.api import Logger
from logger.models import LogClient, LogSubscriber
from logger.sampledata import create_sample_logs
from logger.settings import SETTINGS

TIME_FORMAT = "%Y-%m-%d %H:%M:%S"

class MainPage(webapp.RequestHandler):

    def post(self):
        context = self.request.get('context', '')
        eventtype = self.request.get('eventtype', '')
        time_from = self.request.get('time_from', '')
        time_to = self.request.get('time_to', '')
        msg_key = self.request.get('msg_key', '')
        msg_val = self.request.get('msg_val', '')
        domain = self.request.get('domain', '')
        sort = self.request.get('sort', '-timestamp')
        limit = int(self.request.get('limit', 100))
        filters = []

        if context:
            filters.append(('context =', context))
        if eventtype:
            filters.append(('eventtype =', eventtype))
        if time_from:
            if not ':' in time_from:
                time_from = time_from + ' 00:00:00'
            tf = datetime.datetime.fromtimestamp(
                time.mktime(time.strptime(time_from, TIME_FORMAT)))
            filters.append(('timestamp >=', tf))
        if time_to:
            if not ':' in time_to:
                time_to = time_to + ' 23:59:99'
            tt = datetime.datetime.fromtimestamp(
                time.mktime(time.strptime(time_to, TIME_FORMAT)))
            filters.append(('timestamp <=', tt))
        if msg_key:
            filters.append(('msg_key =', msg_key))
        if msg_val:
            filters.append(('msg_value =', msg_val))
        if domain:
            filters.append(('domain =', domain))

        l = Logger()
        result = l.query(filters=filters,
                         order=sort,
                         limit=limit)

        logentries = result['data']

        self.user = users.get_current_user()

        template_values = {
            'logentries': logentries,
            'context' : context,
            'eventtype' : eventtype,
            'time_from' : time_from,
            'time_to' : time_to,
            'msg_key' : msg_key,
            'msg_val' : msg_val,
            'domain' : domain,
            'sort' : sort,
            'limit' : limit
        }

        path = os.path.join(os.path.dirname(__file__), 'query.html')
        self.response.out.write(template.render(path, template_values))

    def get(self):
        self.post()


class TailPage(webapp.RequestHandler):

    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'tail.html')
        self.response.out.write(template.render(path, {}))


class PostEntryView(webapp.RequestHandler):

    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'post.html')
        self.response.out.write(template.render(path, {}))

    def post(self):
        hsh = self.request.cookies.get('auth', None)
        client = LogClient.all().filter('auth_key =', hsh).get()
        if not client:
            user = users.get_current_user()
            if not user or not users.is_current_user_admin():
                raise users.UserNotFoundError

        domain = self.request.get('domain', None)
        context = self.request.get('context', None)
        eventtype = self.request.get('eventtype', None)

        if not domain or not context or not eventtype:
            self.response.set_status(400, 'Error: domain, context, eventtype are required')
            return
        timestamp = self.request.get('timestamp', None)
        msg_key = self.request.get('msg_key', None)
        msg_val = self.request.get('msg_val', None)

        dt = None

        if timestamp:
            if not ':' in timestamp:
                timestamp = timestamp + ' 00:00:00'
            dt = datetime.datetime.fromtimestamp(
                time.mktime(time.strptime(timestamp, TIME_FORMAT)))

        l = Logger()
        response = l.log(domain, context, msg_key=msg_key,
                         msg_value=msg_val, timestamp=dt,
                         eventtype=eventtype)

        if not client:
            # we came from the /post view 
            path = os.path.join(os.path.dirname(__file__), 'post.html')
            self.response.out.write(template.render(path, {
            'success':True}))
        else:
            self.response.out.write(response)



class ClientsPage(webapp.RequestHandler):
    #TODO: delete with uid instead of name to avoid wrong deletes
    def gen_hash(self, password, salt=None, algorithm='sha256'):
        if isinstance(password, unicode):
            password = password.encode('utf8')
        hash = hashlib.new(algorithm)
        hash.update(password)
        if not salt:
            salt = ''.join([random.choice(ascii_letters + digits) for _ in range(8)])
        hash.update(salt)
        digest = hash.hexdigest()
        return (algorithm, salt, digest)

    def clients(self):
        q = LogClient.all().fetch(1000)
        return q

    def get(self):
        del_hsh = self.request.get('deletehsh', None)
        if del_hsh:
            client = LogClient.all().filter('auth_key =', del_hsh).get()
            client.delete()

        template_values = {
            'clients' : self.clients(),
            'del_hsh' : del_hsh }
        path = os.path.join(os.path.dirname(__file__), 'clients.html')
        self.response.out.write(template.render(path, template_values))

    def post(self):
        name = self.request.get('client_name')
        pw = self.request.get('client_pw')
        hsh = self.gen_hash(pw)

        client = LogClient(name=name, auth_key=hsh[2])
        client.put()

        template_values = {
            'name' : name,
            'hsh' : hsh[2],
            'clients' : self.clients()
            }

        path = os.path.join(os.path.dirname(__file__), 'clients.html')
        self.response.out.write(template.render(path, template_values))

class SubscriptionPage(webapp.RequestHandler):

    @property
    def subscriptions(self):
        q = LogSubscriber.all().fetch(1000)
        return q

    def get(self):

        template_values = {
            'subscriptions' : self.subscriptions
            }
        del_key = self.request.get('delete', None)
        if del_key:
            db.delete(del_key)
            template_values['deleted'] = True

        path = os.path.join(os.path.dirname(__file__), 'subscriptions.html')
        self.response.out.write(template.render(path, template_values))

    def post(self):
        domain = self.request.get('domain', None)
        context = self.request.get('context', None)
        eventtype = self.request.get('eventtype', None)
        msg_key = self.request.get('msg_key', None)
        receiver_type = self.request.get('receiver_type', None)
        receiver_address = self.request.get('receiver_address', None)

        s = LogSubscriber(domain=domain,
                          context=context,
                          eventtype=eventtype,
                          msg_key=msg_key,
                          receiver_type=receiver_type,
                          receiver_address=receiver_address)
        s.put()

        template_values = {
            'subscriptions' : self.subscriptions,
            'created' : True
            }

        path = os.path.join(os.path.dirname(__file__), 'subscriptions.html')
        self.response.out.write(template.render(path, template_values))



class SettingsPage(webapp.RequestHandler):

    def render(self):
        template_values = {
            'entries' : SETTINGS.getall()}
        path = os.path.join(os.path.dirname(__file__), 'settings.html')
        self.response.out.write(template.render(path, template_values))

    def get(self):
        self.render()

    def post(self):
        for key,val in self.request.params.items():
            SETTINGS.set(key,val)
        self.render()


class SendXMPP(webapp.RequestHandler):
    def get(self):
        msg=self.request.get('msg', 'hallo welt')
        jid=self.request.get('jid', None)
        chat_message_sent = False
        jid_sender = SETTINGS.get('jid_sender')
        logging.debug('%s send jabber to %s msg: %s' % \
                      (jid_sender, jid ,msg))
        presence = xmpp.get_presence(jid, jid_sender)
        if presence:
            status_code = xmpp.send_message(jid, msg,
                                            from_jid=jid_sender)
            chat_message_sent = (status_code != xmpp.NO_ERROR)
        self.response.out.write(
            'XMPP Message sent: from %s to %s: %s Userstatus: %s' % \
                                    (jid, jid_sender, chat_message_sent,
                                     presence))


class InviteXMPP(webapp.RequestHandler):
    def get(self):
        sender = SETTINGS.get('jid_sender')
        jid = self.request.get('jid', None)
        xmpp.send_invite(jid, from_jid=sender)
        self.redirect("/clients")


class SampleData(webapp.RequestHandler):

    def get(self):
        create_sample_logs()
        self.response.out.write('sampledata created')


